#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import time
import os
import sys
from collections import namedtuple
import argparse
from stat import * # ST_SIZE etc
import zipfile

zbyvajiciMistoNaDisku = 10 # kdyz je na disku alespon 10% volneho mista
#casovyTest = 60*60*24*7 # sekund*minut*hodin*dnu
casovyTest = 60*20*1*1 # sekund*minut*hodin*dnu
hledanePriponySouboru = (".dwg",)

class DwgBackup(object):
    """
    prochazi zadany adresar, hleda soubory, ktere jsou mladsi nez casovy test  
    do nazvu kazdeho nalezeneho souboru prida casove razitko
    kopii souboru ulozi do ciloveho (zalohovaciho) adresare vcetne adresrove struktury 
    v pripade, ze je v cilovem adresari malo mista, odesle na zadanou adresu varovny mail
    """
    def __init__(self, sourceDir, targetDir, verbose, testOnly):
        self.sourceDir = sourceDir
        self.targetDir = targetDir        
        self.verbose = verbose
        self.testOnly = testOnly
        self.freeDiskSpacePercent = self.freeDiskSpace()             
       
    def freeDiskSpace(self):        
        """Return disk usage statistics about the given path.
    
        Returned valus is a named tuple with attributes 'total', 'used' and
        'free', which are the amount of total, used and free space, in bytes.
        """
        st = os.statvfs(self.targetDir)
        free = st.f_bavail * st.f_frsize
        total = st.f_blocks * st.f_frsize
        used = (st.f_blocks - st.f_bfree) * st.f_frsize        
        freeDiskSpacePercent = (free*1.0/total)*100  
        if self.verbose:
            print "%0.2f%% kapacity disku je volných" % freeDiskSpacePercent
        return freeDiskSpacePercent
    
    def findDwgFiles(self):        
        for root, dirs, files in os.walk(self.sourceDir):            
            for file in files:
                if file.endswith(hledanePriponySouboru):
                    self.fullFileName = os.path.join(root, file)
                    #print self.fullFileName                    
                    if os.path.isfile(self.fullFileName):
                        #print "files:", files
                        self.fileName = file
                        self.fileNameNoExtension, ext = os.path.splitext(file)
                        info = os.stat(self.fullFileName)
                        self.fileTimeModification = info[ST_MTIME]
                        yield self.fullFileName

    def makeSurePahtExists(self):        
        self.targetPath = self.targetDir + os.path.dirname(self.fullFileName)
        self.targetPath = self.targetPath.replace('//','/')     
        self.targetPath = self.targetPath.replace(self.sourceDir, '')
        if ".recycle/" in self.targetPath:
            if self.verbose:
                print "recycle bin nezalohujeme"
            return 
        if self.testOnly:
            print "testovací režim, adresář: %s nebude vytvořen" % self.targetPath
            return
        try:            
            os.makedirs(self.targetPath)
            if self.verbose:
                print "vytvářím adresář: %s" % self.targetPath
        except OSError:
            if os.path.isdir(self.targetPath):
                # We are nearly safe
                pass                
            else:
                # There was an error on creation, so make sure we know about it
                raise
                
        
                
    def createZipFile(self):  
        timeFileModified = time.gmtime(os.stat(self.fullFileName).st_mtime)
        timeFileModified = time.strftime("%Y%m%d_%H%M%S", timeFileModified)                
        zipFileName = "%s_%s%s" % (self.fileNameNoExtension, timeFileModified, ".zip")        
        zipFullFileName = os.path.join(self.targetPath, zipFileName)
        if ".recycle/" in self.targetPath:
            if self.verbose:
                print "recycle bin nezalohujeme"
            return
        if self.testOnly:
            print "testovací režim, archiv %s nebude vytvořen" % zipFullFileName
            return
        if self.verbose:            
            print zipFullFileName 
        f = zipfile.ZipFile(zipFullFileName, "w")
        self.fileName = self.fileName.decode('utf-8')
        self.fileName = self.fileName.encode('CP852') # Latin2
        f.write(self.fullFileName, self.fileName, zipfile.ZIP_DEFLATED)
        f.close()


if __name__ == "__main__":
    import argparse  
    
    myDescription = """    
        Ve zdrojovém adresáři projde rekurzivně všechny podadresáře. 
        Hledá všechny soubory s extenzí dwg, které jsou mladší než akutuální čas mínus zadaný počet minut.
        Každý nalezený soubor je zkomprimován.
        Zkomprimovaný soubor je pojmenován stejným názvem rozšířeným o Time Stamp (ve tvaru YYYY-MM-DD) 
        a je uložen do cílového adresáře.
        V cílovém adresáři je vytvářena stejná adresářová strukturu, jako má zdrojový adresář.    
        """

    parser = argparse.ArgumentParser(description= myDescription)
    
    parser.add_argument('-z', '--zdroj', metavar="/zdroj", 
                        type= str, dest = "zdroj",  required = True, 
                        help='zdrojový adresář, např: /home/autocad')
                        
    parser.add_argument('-c', '--cil', metavar="/cil",  
                        type=str, dest = "cil", required = True, 
                        help='cílový adresář, např: /backup/autocad')
    
                      
    parser.add_argument("-v", "--verbose",
                      action="store_true", dest="verbose",
                      default=False,
                      help="vypisuje hlášky do stdout")
                      
    parser.add_argument("-f", "--full",
                      action="store_false", dest="testOnly",
                      default=True,
                      help="ostrý běh skriptu, nalezené soubory budou uloženy do cílového adresáře")                      
  
    
    args = parser.parse_args()
    if not os.path.exists(args.zdroj):
        print "cesta %s neexistuje" % args.zdroj
        sys.exit()
    if not os.path.exists(args.cil):
        print "cesta %s neexistuje"% args.cil
        sys.exit()
    
    if args.verbose:
        print("Nalezené soubory budou vypisovany na displej.")


    backuper = DwgBackup(args.zdroj, args.cil, args.verbose, args.testOnly)
    if backuper.freeDiskSpacePercent >= zbyvajiciMistoNaDisku:
        
        now = time.time()
        fileGen = backuper.findDwgFiles()
        while 1:
            try:
                next(fileGen)                
                if backuper.fileTimeModification > now-casovyTest:
                    backuper.makeSurePahtExists()
                    backuper.createZipFile()
        
            except StopIteration:
                if args.verbose:
                    print "zálohování úspěšně dokončeno"
                break
    else:
        import mailer
        address = ["futera@atlanthk.cz", "petr.jakes.tpc@gmail.com", ]
        text = "na disku není dostatek místa, záloha souborů .dwg neproběhla úspěšně"
        text = text.decode('utf-8')
        text = text.encode('CP1250')
        subject = "server Atlant, nedostatek místa na disku"
        subject = subject.decode('utf-8')
        subject = subject.encode('CP1250')
        mailer.newSendMail(text= text, subject = subject, to = address)

